/*
 * fast_trigonometry.cpp
 * This file is part of OCI (Open Chicken Invaders)
 *
 * Copyright (C) 2010-2014 - Aleksey Konovalov (konovalov.aleks@gmail.com)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Library General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "fast_trigonometry.h"

#include "array_size.h"
#include <assert.h>
#include <stdlib.h>

namespace trigonometry {

    static const float SIN_VALUES[360] = {
        0.000000, 0.017452, 0.034899, 0.052336, 0.069756, 0.087156,
        0.104528, 0.121869, 0.139173, 0.156434, 0.173648, 0.190809,
        0.207912, 0.224951, 0.241922, 0.258819, 0.275637, 0.292372,
        0.309017, 0.325568, 0.342020, 0.358368, 0.374607, 0.390731,
        0.406737, 0.422618, 0.438371, 0.453990, 0.469472, 0.484810,
        0.500000, 0.515038, 0.529919, 0.544639, 0.559193, 0.573576,
        0.587785, 0.601815, 0.615661, 0.629320, 0.642788, 0.656059,
        0.669131, 0.681998, 0.694658, 0.707107, 0.719340, 0.731354,
        0.743145, 0.754710, 0.766044, 0.777146, 0.788011, 0.798636,
        0.809017, 0.819152, 0.829038, 0.838671, 0.848048, 0.857167,
        0.866025, 0.874620, 0.882948, 0.891007, 0.898794, 0.906308,
        0.913545, 0.920505, 0.927184, 0.933580, 0.939693, 0.945519,
        0.951057, 0.956305, 0.961262, 0.965926, 0.970296, 0.974370,
        0.978148, 0.981627, 0.984808, 0.987688, 0.990268, 0.992546,
        0.994522, 0.996195, 0.997564, 0.998630, 0.999391, 0.999848,
        1.000000, 0.999848, 0.999391, 0.998630, 0.997564, 0.996195,
        0.994522, 0.992546, 0.990268, 0.987688, 0.984808, 0.981627,
        0.978148, 0.974370, 0.970296, 0.965926, 0.961262, 0.956305,
        0.951057, 0.945519, 0.939693, 0.933580, 0.927184, 0.920505,
        0.913545, 0.906308, 0.898794, 0.891007, 0.882948, 0.874620,
        0.866025, 0.857167, 0.848048, 0.838671, 0.829038, 0.819152,
        0.809017, 0.798636, 0.788011, 0.777146, 0.766044, 0.754710,
        0.743145, 0.731354, 0.719340, 0.707107, 0.694658, 0.681998,
        0.669131, 0.656059, 0.642788, 0.629320, 0.615661, 0.601815,
        0.587785, 0.573576, 0.559193, 0.544639, 0.529919, 0.515038,
        0.500000, 0.484810, 0.469472, 0.453990, 0.438371, 0.422618,
        0.406737, 0.390731, 0.374607, 0.358368, 0.342020, 0.325568,
        0.309017, 0.292372, 0.275637, 0.258819, 0.241922, 0.224951,
        0.207912, 0.190809, 0.173648, 0.156434, 0.139173, 0.121869,
        0.104528, 0.087156, 0.069756, 0.052336, 0.034899, 0.017452,
        0.000000, -0.017452, -0.034899, -0.052336, -0.069756, -0.087156,
        -0.104528, -0.121869, -0.139173, -0.156434, -0.173648, -0.190809,
        -0.207912, -0.224951, -0.241922, -0.258819, -0.275637, -0.292372,
        -0.309017, -0.325568, -0.342020, -0.358368, -0.374607, -0.390731,
        -0.406737, -0.422618, -0.438371, -0.453990, -0.469472, -0.484810,
        -0.500000, -0.515038, -0.529919, -0.544639, -0.559193, -0.573576,
        -0.587785, -0.601815, -0.615661, -0.629320, -0.642788, -0.656059,
        -0.669131, -0.681998, -0.694658, -0.707107, -0.719340, -0.731354,
        -0.743145, -0.754710, -0.766044, -0.777146, -0.788011, -0.798636,
        -0.809017, -0.819152, -0.829038, -0.838671, -0.848048, -0.857167,
        -0.866025, -0.874620, -0.882948, -0.891007, -0.898794, -0.906308,
        -0.913545, -0.920505, -0.927184, -0.933580, -0.939693, -0.945519,
        -0.951057, -0.956305, -0.961262, -0.965926, -0.970296, -0.974370,
        -0.978148, -0.981627, -0.984808, -0.987688, -0.990268, -0.992546,
        -0.994522, -0.996195, -0.997564, -0.998630, -0.999391, -0.999848,
        -1.000000, -0.999848, -0.999391, -0.998630, -0.997564, -0.996195,
        -0.994522, -0.992546, -0.990268, -0.987688, -0.984808, -0.981627,
        -0.978148, -0.974370, -0.970296, -0.965926, -0.961262, -0.956305,
        -0.951057, -0.945519, -0.939693, -0.933580, -0.927184, -0.920505,
        -0.913545, -0.906308, -0.898794, -0.891007, -0.882948, -0.874620,
        -0.866025, -0.857167, -0.848048, -0.838671, -0.829038, -0.819152,
        -0.809017, -0.798636, -0.788011, -0.777146, -0.766044, -0.754710,
        -0.743145, -0.731354, -0.719340, -0.707107, -0.694658, -0.681998,
        -0.669131, -0.656059, -0.642788, -0.629320, -0.615661, -0.601815,
        -0.587785, -0.573576, -0.559193, -0.544639, -0.529919, -0.515038,
        -0.500000, -0.484810, -0.469472, -0.453990, -0.438371, -0.422618,
        -0.406737, -0.390731, -0.374607, -0.358368, -0.342020, -0.325568,
        -0.309017, -0.292372, -0.275637, -0.258819, -0.241922, -0.224951,
        -0.207912, -0.190809, -0.173648, -0.156434, -0.139173, -0.121869,
        -0.104528, -0.087156, -0.069756, -0.052336, -0.034899, -0.017452
    };

    float sin(Degree angle) {
        assert(angle.Value() >= 0 && static_cast<size_t>(angle.Value()) <= ARRAY_SIZE(SIN_VALUES));
        return SIN_VALUES[angle.Value()];
    }

    static const float COS_VALUES[360] = {
        1.000000, 0.999848, 0.999391, 0.998630, 0.997564, 0.996195,
        0.994522, 0.992546, 0.990268, 0.987688, 0.984808, 0.981627,
        0.978148, 0.974370, 0.970296, 0.965926, 0.961262, 0.956305,
        0.951057, 0.945519, 0.939693, 0.933580, 0.927184, 0.920505,
        0.913545, 0.906308, 0.898794, 0.891007, 0.882948, 0.874620,
        0.866025, 0.857167, 0.848048, 0.838671, 0.829038, 0.819152,
        0.809017, 0.798636, 0.788011, 0.777146, 0.766044, 0.754710,
        0.743145, 0.731354, 0.719340, 0.707107, 0.694658, 0.681998,
        0.669131, 0.656059, 0.642788, 0.629320, 0.615661, 0.601815,
        0.587785, 0.573576, 0.559193, 0.544639, 0.529919, 0.515038,
        0.500000, 0.484810, 0.469472, 0.453990, 0.438371, 0.422618,
        0.406737, 0.390731, 0.374607, 0.358368, 0.342020, 0.325568,
        0.309017, 0.292372, 0.275637, 0.258819, 0.241922, 0.224951,
        0.207912, 0.190809, 0.173648, 0.156434, 0.139173, 0.121869,
        0.104528, 0.087156, 0.069756, 0.052336, 0.034899, 0.017452,
        0.000000, -0.017452, -0.034899, -0.052336, -0.069756, -0.087156,
        -0.104528, -0.121869, -0.139173, -0.156434, -0.173648, -0.190809,
        -0.207912, -0.224951, -0.241922, -0.258819, -0.275637, -0.292372,
        -0.309017, -0.325568, -0.342020, -0.358368, -0.374607, -0.390731,
        -0.406737, -0.422618, -0.438371, -0.453990, -0.469472, -0.484810,
        -0.500000, -0.515038, -0.529919, -0.544639, -0.559193, -0.573576,
        -0.587785, -0.601815, -0.615661, -0.629320, -0.642788, -0.656059,
        -0.669131, -0.681998, -0.694658, -0.707107, -0.719340, -0.731354,
        -0.743145, -0.754710, -0.766044, -0.777146, -0.788011, -0.798636,
        -0.809017, -0.819152, -0.829038, -0.838671, -0.848048, -0.857167,
        -0.866025, -0.874620, -0.882948, -0.891007, -0.898794, -0.906308,
        -0.913545, -0.920505, -0.927184, -0.933580, -0.939693, -0.945519,
        -0.951057, -0.956305, -0.961262, -0.965926, -0.970296, -0.974370,
        -0.978148, -0.981627, -0.984808, -0.987688, -0.990268, -0.992546,
        -0.994522, -0.996195, -0.997564, -0.998630, -0.999391, -0.999848,
        -1.000000, -0.999848, -0.999391, -0.998630, -0.997564, -0.996195,
        -0.994522, -0.992546, -0.990268, -0.987688, -0.984808, -0.981627,
        -0.978148, -0.974370, -0.970296, -0.965926, -0.961262, -0.956305,
        -0.951057, -0.945519, -0.939693, -0.933580, -0.927184, -0.920505,
        -0.913545, -0.906308, -0.898794, -0.891007, -0.882948, -0.874620,
        -0.866025, -0.857167, -0.848048, -0.838671, -0.829038, -0.819152,
        -0.809017, -0.798636, -0.788011, -0.777146, -0.766044, -0.754710,
        -0.743145, -0.731354, -0.719340, -0.707107, -0.694658, -0.681998,
        -0.669131, -0.656059, -0.642788, -0.629320, -0.615661, -0.601815,
        -0.587785, -0.573576, -0.559193, -0.544639, -0.529919, -0.515038,
        -0.500000, -0.484810, -0.469472, -0.453990, -0.438371, -0.422618,
        -0.406737, -0.390731, -0.374607, -0.358368, -0.342020, -0.325568,
        -0.309017, -0.292372, -0.275637, -0.258819, -0.241922, -0.224951,
        -0.207912, -0.190809, -0.173648, -0.156434, -0.139173, -0.121869,
        -0.104528, -0.087156, -0.069756, -0.052336, -0.034899, -0.017452,
        -0.000000, 0.017452, 0.034899, 0.052336, 0.069756, 0.087156,
        0.104528, 0.121869, 0.139173, 0.156434, 0.173648, 0.190809,
        0.207912, 0.224951, 0.241922, 0.258819, 0.275637, 0.292372,
        0.309017, 0.325568, 0.342020, 0.358368, 0.374607, 0.390731,
        0.406737, 0.422618, 0.438371, 0.453990, 0.469472, 0.484810,
        0.500000, 0.515038, 0.529919, 0.544639, 0.559193, 0.573576,
        0.587785, 0.601815, 0.615661, 0.629320, 0.642788, 0.656059,
        0.669131, 0.681998, 0.694658, 0.707107, 0.719340, 0.731354,
        0.743145, 0.754710, 0.766044, 0.777146, 0.788011, 0.798636,
        0.809017, 0.819152, 0.829038, 0.838671, 0.848048, 0.857167,
        0.866025, 0.874620, 0.882948, 0.891007, 0.898794, 0.906308,
        0.913545, 0.920505, 0.927184, 0.933580, 0.939693, 0.945519,
        0.951057, 0.956305, 0.961262, 0.965926, 0.970296, 0.974370,
        0.978148, 0.981627, 0.984808, 0.987688, 0.990268, 0.992546,
        0.994522, 0.996195, 0.997564, 0.998630, 0.999391, 0.999848
    };

    float cos(Degree angle) {
        assert(angle.Value() >= 0 && static_cast<size_t>(angle.Value()) <= ARRAY_SIZE(COS_VALUES));
        return COS_VALUES[angle.Value()];
    }

} // namespae trigonometry
